
cmake_minimum_required(VERSION 3.16)
project(cpp_test CXX C)
message(STATUS "Building project: ${PROJECT_NAME}")

# set c++ && c standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)

# platform detect
if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux")
    message(STATUS "current platform: Linux")
elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
    message(STATUS "current platform: Windows")
else()
	message(STATUS "unkown platform: ${CMAKE_HOST_SYSTEM_NAME}")
endif()

# check compiler features
# message(STATUS "C++ compiler supports these features:")
# foreach(i ${CMAKE_CXX_COMPILE_FEATURES})
#   message(STATUS "${i}")
# endforeach()

# add compiler options
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
    message(STATUS "current compiler: Clang ")
    add_compile_options(
        -Wno-deprecated-declarations
        -Wno-unused-command-line-argument
    )
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
    message(STATUS "current compiler: GNU ")
    add_compile_options(-Wall)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
    message(STATUS "current compiler: MSVC ")
    add_compile_options(/utf-8)
else()
    message(STATUS "current compiler: ${CMAKE_CXX_COMPILER_ID}")
endif()

# add thirdparty
add_subdirectory(thirdparty/spdlog)
add_subdirectory(thirdparty/googletest)
add_subdirectory(thirdparty/benchmark)

# add log_service_lib
add_library(log_service_lib
    log_service/library/log_service.cc
    log_service/library/log_service_impl.cc
)
target_link_libraries(log_service_lib PUBLIC spdlog::spdlog)
target_include_directories(log_service_lib PUBLIC "log_service/library")
target_include_directories(log_service_lib PRIVATE "log_service/library/internal")

file(GLOB COMMON_SRCS common/*.cc common/*.cpp common/*.c)
add_library(common_lib ${COMMON_SRCS})
target_include_directories(common_lib PUBLIC "common")

# add applications executables
set(SOURCE_DIR source)
file(GLOB ALL_ITEMS ${SOURCE_DIR}/*)
foreach(ITEM ${ALL_ITEMS})
    if(IS_DIRECTORY ${ITEM})
        get_filename_component(EXE_NAME ${ITEM} NAME_WE)
        message(STATUS "Target: ${EXE_NAME}")
        file(GLOB_RECURSE SOURCES ${ITEM}/*.cc ${ITEM}/*.c)
        add_executable(${EXE_NAME} ${SOURCES})
        if(EXISTS "${ITEM}/target.cmake")
            set(APP_SRCS ${SOURCES})
            set(APP_NAME ${EXE_NAME})
            set(APP_SRCS_DIR ${ITEM})
            include(${ITEM}/target.cmake)
            unset(APP_SRCS)
            unset(APP_NAME)
            unset(APP_SRCS_DIR)
        endif()
        target_link_libraries(${EXE_NAME} PRIVATE log_service_lib common_lib)
        if (CMAKE_SYSTEM_NAME MATCHES "Windows")
            target_link_libraries(${EXE_NAME} PRIVATE ws2_32)
        else()
            target_link_libraries(${EXE_NAME} PRIVATE pthread)
        endif()
        target_include_directories(${EXE_NAME} PRIVATE ${ITEM})
    endif()
endforeach()

# add benchmark executables
set(BENCHMARK_TEST_DIR benchmark)
file(GLOB BENCHMARK_TEST_SRCS ${BENCHMARK_TEST_DIR}/*.cc)
foreach(ITEM ${BENCHMARK_TEST_SRCS})
    get_filename_component(BM_FILE_NAME ${ITEM} NAME_WLE)
    set(EXE_NAME bm_${BM_FILE_NAME})
    message(STATUS "Benchmark: ${EXE_NAME}")
    add_executable(${EXE_NAME} ${ITEM})
    target_link_libraries(${EXE_NAME} PRIVATE common_lib benchmark::benchmark_main)
    if (CMAKE_SYSTEM_NAME MATCHES "Windows")
        target_link_libraries(${EXE_NAME} PRIVATE ws2_32)
    else()
        target_link_libraries(${EXE_NAME} PRIVATE pthread)
    endif()
    target_include_directories(${EXE_NAME} PRIVATE ${BENCHMARK_TEST_DIR})
endforeach()

# add ctest of gtest executables
enable_testing()
include(CTest)
set(GTEST_TEST_DIR gtest)
file(GLOB GTEST_TEST_SRCS ${GTEST_TEST_DIR}/*.cc)
add_executable(cpp_gtest ${GTEST_TEST_SRCS})
target_link_libraries(cpp_gtest PRIVATE common_lib GTest::gtest_main)
if (CMAKE_SYSTEM_NAME MATCHES "Windows")
    target_link_libraries(cpp_gtest PRIVATE ws2_32)
else()
    target_link_libraries(cpp_gtest PRIVATE pthread)
endif()
include(GoogleTest)
gtest_discover_tests(cpp_gtest)
